#ifndef TIEC_FOUNDATION_H
#define TIEC_FOUNDATION_H

#include "macro.h"
#include "data.h"
#include "file.h"

namespace NS_TIEC {
  static String kSourceExtension = "t";
  static String kIrExtension = "tir";
  static String kBytecodeExtension = "tcs";

  /// 输入文件类型定义
  enum FileCategory {
    /// 源代码
    Source = 0,
    /// IR中间代码
    Ir = 1,
    /// 字节码
    Bytecode = 2
  };

  /// 编译器输入文件抽象接口
  class TiecodeSource {
  public:
    /// 获取输入文件的名称
    /// \return 文件名
    virtual String getName() = 0;

    /// 获取文件最后修改时间
    /// \return 时间戳
    virtual UInt64 lastModified() = 0;

    /// 读取文件内容
    /// \return 文件的全部内容
    virtual String readContent() = 0;

    /// 获取URI
    /// \return URI
    virtual Uri getUri() = 0;

    /// 获取文件路径
    /// \return 文件绝对路径
    virtual String getPath() = 0;

    /// 获取输入源关联子输入源合并编译
    /// \return 子输入源集合
    virtual List<PTR<TiecodeSource>> childSources() = 0;

    /// 获取文件类型
    /// \return 当前文件的类型
    virtual FileCategory getCategory() = 0;
  };

  /// 本地文件输入源
  class TiecodeFileSource : public TiecodeSource {
  public:
    explicit TiecodeFileSource(const File& file);
    explicit TiecodeFileSource(const File& file, List<File> child_files);

    String getName() override;

    UInt64 lastModified() override;

    String readContent() override;

    Uri getUri() override;

    String getPath() override;

    List<PTR<TiecodeSource>> childSources() override;

    FileCategory getCategory() override;
  private:
    File file_;
    List<PTR<TiecodeSource>> child_sources_;
  };

  /// 位置描述
  struct Position {
    UInt32 line;
    UInt32 column;
    UInt32 index;

    /// 将当前Position加上指定长度得到新的position
    /// \param length 长度
    /// \return 新的Position
    Position plusLength(UInt32 length);
  };

  /// 范围描述
  struct Range {
    Position start;
    Position end;
  };

  /// 语法树位置范围描述
  struct Origin {
    PTR<TiecodeSource> source;
    Range range;
  };

  /// 名称接口定义
  class Name {
  public:
    /// 转换为string
    virtual String asString() = 0;

    /// 获取字符长度
    /// \return 总字符长度
    virtual UInt64 length() = 0;

    /// 查找某个字符在Name中的位置
    /// \param ch 字符
    virtual UInt64 indexOf(char ch) = 0;

    /// 判断内容是否和某个字符串相同
    /// \param text 文本
    /// \return 相同返回true，否则false
    virtual bool contentSameAs(const String& text) = 0;
  };

  /// 日志等级
  enum LogLevel {
    kLevelDebug = 0,
    kLevelInfo = 1,
    kLevelWarning = 2,
    kLevelError = 3,
    kLevelFatal = 4,
  };

  /// 诊断信息
  struct Diagnostic {
    String uri;
    Range range;
    String key;
    String message;
    LogLevel level;

    Diagnostic();

    explicit Diagnostic(const String& message);

    Diagnostic(const String& message, LogLevel level);

    Diagnostic(const String& uri, const Range& range, const String& message, const String& key);

    Diagnostic(const String& uri, const Range& range, const String& key, const String& message, LogLevel level);
  };
}
#endif //TIEC_FOUNDATION_H
